#include "datacomparison.h"


#include <functional>

#include <QMap>
#include <QString>
#include <QDebug>
#include <QSqlQueryModel>
#include <QSqlRecord>

struct DataComparisonPrivate {
    QMap<QString, std::function<bool(const QString &, const QString &)>> actionMap;//创建一个QMap来存储字符串到函数的映射
};

DataComparison &DataComparison::instance()
{
    static DataComparison instance;
    return instance;
}

QList<int> DataComparison::findByModel(const QSqlQueryModel *model_find, const QVector<ConditionData> &conditionDatas, const QString &idKey)
{
    QList<int> idList;
    for(int i=0;i<model_find->rowCount();i++)
    {
        QSqlRecord curRec=model_find->record(i);
        if (curRec.isEmpty()) continue;
        bool result = true;
        for (const auto& conditionData: conditionDatas) {
            if (!curRec.contains(conditionData.tableKey)) {
                result = false;
                break;
            }
            const auto& tableValue = curRec.value(conditionData.tableKey).toString();
            result = actionMapExecute(tableValue, conditionData.condition, conditionData.b);
            if (!result) break;

        }
        if (!result) continue;
        idList.append(curRec.value(idKey).toInt());
    }
    return idList;
}

QList<int> DataComparison::findByModel(const QList<QVariantMap> &model_find, const QVector<ConditionData> &conditionDatas, const QString &idKey)
{
    QList<int> idList;
    for(int i=0; i< model_find.size(); i++)
    {
        auto curRec=model_find.at(i);
        if (curRec.isEmpty()) continue;
        bool result = true;
        for (const auto& conditionData: conditionDatas) {
            if (!curRec.contains(conditionData.tableKey)) {
                result = false;
                break;
            }
            const auto& tableValue = curRec.value(conditionData.tableKey).toString();
            result = actionMapExecute(tableValue, conditionData.condition, conditionData.b);
            if (!result) break;

        }
        if (!result) continue;
        idList.append(curRec.value(idKey).toInt());
    }
    return idList;
}

DataComparison::DataComparison() {

    m_data = new DataComparisonPrivate();

    m_data->actionMap["equal"]=equalStrFunc;
    m_data->actionMap["not equal"]=notEqualStrFunc;
    m_data->actionMap["contain"]=containStrFunc;
    m_data->actionMap["exclude"]=excludeStrFunc;
    m_data->actionMap[">"]=greaterStrFunc;
    m_data->actionMap["<"]=greaterStrFunc;
    m_data->actionMap[">="]=greaterEqualStrFunc;
    m_data->actionMap["<="]=smallerEqualStrFunc;

}

DataComparison::~DataComparison()
{
    delete m_data;
    m_data = nullptr;
}


// 检查映射中是否包含该动作，并执行它
bool DataComparison::actionMapExecute(const QString &a,const QString &condition,const QString &b)
{
    // 检查映射中是否包含该动作，并执行它
    if (m_data->actionMap.contains(condition)) {
        bool result=m_data->actionMap[condition](a,b); // 调用与字符串键匹配的函数
        if(result==false)
        {
            return false;
        }
    } else {
        qDebug()<< "Unknown action." ;
    }

    return true;
}


//判断字符串相等equal
bool DataComparison::equalStrFunc(const QString &a,const QString &b)
{
    return a==b;
}
//判断字符串不相等not equal
bool DataComparison::notEqualStrFunc(const QString &a,const QString &b)
{
    return a!=b;
}
//判断字符串a包含字符串b contain
bool DataComparison::containStrFunc(const QString &a,const QString &b)
{
    return a.contains(b);
}
//判断字符串a不包含字符串b exclude
bool DataComparison::excludeStrFunc(const QString &a,const QString &b)
{
    return !(a.contains(b));
}
//判断字符串a＞b >
bool DataComparison::greaterStrFunc(const QString &a,const QString &b)
{
    return a>b;
}
//判断字符串a<b <
bool DataComparison::smallerStrFunc(const QString &a,const QString &b)
{
    return a<b;
}
//判断字符串a＞=b ＞=
bool DataComparison::greaterEqualStrFunc(const QString &a,const QString &b)
{
    return a>=b;
}
//判断字符串a＜=b ＜=
bool DataComparison::smallerEqualStrFunc(const QString &a,const QString &b)
{
    return a<=b;
}
